/*
 * Cloud9: A MapReduce Library for Hadoop
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0 
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

package apweb;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Iterator;
import java.util.Random;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.Reducer.Context;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import org.apache.log4j.Logger;

/**
 * <p>
 * gernate a random data, output, key:number, value:number
 * </p>
 * 
 * <ul>
 * <li>[input-path] input path</li>
 * <li>[output-path] output path</li>
 * <li>[join column index in left table]</li>
 * <li>[join column index in right table]</li>
 * <li>[num-reducers] number of reducers</li>
 * </ul>
 * 
 * @author Jimmy Lin
 */
public class TestMapReduceOverRandomData extends Configured implements Tool {
	private static final Logger sLogger = Logger.getLogger(TestMapReduceOverRandomData.class);

	// mapper: emits (token, 1) for every word occurrence
	private static class MyMapper extends Mapper<LongWritable, Text, Text, Text> {

		// reuse objects to save overhead of object creation
		Random randomGenerator = new Random();
		
		@Override
		public void map(LongWritable key, Text value, Context context) throws IOException,
				InterruptedException {
			//
			context.write(new Text(String.valueOf(key)), value);
		}
	}
	
	private static class MyReducer extends Reducer<Text, Text, Text, Text> {

		// reuse objects
		private final static IntWritable SumValue = new IntWritable();
		
//		private static String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";  
//		private static String dbURL = "jdbc:sqlserver://192.9.200.41:1433; DatabaseName=graph";   
//		private static String userName = "sa";   
//		private static String userPwd = "1638";   
//		private static Connection dbConn;

		@Override
		public void reduce(Text key, Iterable<Text> values,
				Context context) throws IOException, InterruptedException {
			// sum up values
			Iterator<Text> iter = values.iterator();
			int sum = 0;
			while (iter.hasNext()) {
				sum ++;
			}
			SumValue.set(sum);
			context.write(key, new Text(String.valueOf(sum)));
			/*
			try {
				   Class.forName(driverName);
				   dbConn = DriverManager.getConnection(dbURL, userName, userPwd);
				   Statement st = dbConn.createStatement();
				   String SQLStatement = "insert into zjiashtest VALUES ('"+key.toString()+"',100 )";
				   st.execute(SQLStatement);
			   } catch (Exception e) {
				   e.printStackTrace();
			   }	
			   */
		}
		
	}

	

	/**
	 * Creates an instance of this tool.
	 */
	public TestMapReduceOverRandomData() {
	}

	private static int printUsage() {
		System.out.println("usage: [input-path] [num-reducers]");
		ToolRunner.printGenericCommandUsage(System.out);
		return -1;
	}

	/**
	 * Runs this tool.
	 */
	public int run(String[] args) throws Exception {
		if (args.length != 2) {
			printUsage();
			return -1;
		}

		String inputPath = args[0];
		String outputPath = args[0]+"."+Math.random();
		int reduceTasks = Integer.parseInt(args[1]);

		sLogger.info("Tool: DemoWordCount");
		sLogger.info(" - input path: " + inputPath);
		sLogger.info(" - output path: " + outputPath);
		sLogger.info(" - number of reduceTasks: " + reduceTasks);

		Configuration conf = new Configuration();

		Job job = new Job(conf, "TestMapReduceOverRandomData");
		job.setJarByClass(TestMapReduceOverRandomData.class);

		job.setNumReduceTasks(reduceTasks);

		FileInputFormat.setInputPaths(job, new Path(inputPath));
		FileOutputFormat.setOutputPath(job, new Path(outputPath));

		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);

		job.setMapperClass(MyMapper.class);
//		job.setCombinerClass(MyReducer.class);
		job.setReducerClass(MyReducer.class);

		// Delete the output directory if it exists already
		Path outputDir = new Path(outputPath);
		FileSystem.get(conf).delete(outputDir, true);

		long startTime = System.currentTimeMillis();
		job.waitForCompletion(true);
		sLogger.info("Job TestMapReduce Finished in " + (System.currentTimeMillis() - startTime) / 1000.0
				+ " seconds");

		return 0;
	}

	/**
	 * Dispatches command-line arguments to the tool via the
	 * <code>ToolRunner</code>.
	 */
	public static void main(String[] args) throws Exception {
		int res = ToolRunner.run(new Configuration(), new TestMapReduceOverRandomData(), args);
		System.exit(res);
	}
}
